package engine

type ConcurrentEngine struct {
	Scheduler        Scheduler
	WorkerCount      int
	ItemChan         chan Item
	RequestProcessor Processor
}
type Processor func(Request) (ParseResult, error)
type Scheduler interface {
	ReadyNotifier
	Submit(Request)
	ConfigureWorkerChan() chan Request
	Run()
}
type ReadyNotifier interface {
	WorkReady(chan Request)
}

func (e *ConcurrentEngine) Run(seeds ...Request) {

	out := make(chan ParseResult)
	e.Scheduler.Run()
	for i := 0; i < e.WorkerCount; i++ {
		e.createWorker(e.Scheduler.ConfigureWorkerChan(), out, e.Scheduler)
	}
	for _, r := range seeds {
		e.Scheduler.Submit(r)
	}
	profileCount := 0
	for {
		result := <-out
		for _, item := range result.Items {

			var i = item
			//log.Printf("Go item #%v: %v", profileCount,item)
			profileCount++
			go func() { e.ItemChan <- i }()

		}
		for _, request := range result.Request {
			e.Scheduler.Submit(request)
		}
	}
}
func (e *ConcurrentEngine) createWorker(in chan Request, out chan ParseResult, notifier ReadyNotifier) {
	go func() {
		for {
			notifier.WorkReady(in)
			request := <-in
			result, err := e.RequestProcessor(request) //call rpc
			if err != nil {
				continue
			}
			out <- result
		}
	}()

}
